#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <vector>
using namespace std;

typedef vector<int> vint;
typedef vector< int>   vuint;
typedef vector< bool>   vbool; 
typedef vector< vector<bool> > vvbool;
typedef vector< vector<int> > vvint;
typedef pair<int,int> par;

bool debug = true;

#define DBG(X) if (debug) cerr << #X << " = " << X << endl;
#define DBGComment(String) if (debug) cerr << #String << endl;
#define DBGAssert(ExpresionBooleana) if (debug && ExpresionBooleana) cerr << #ExpresionBooleana << " ? " << false << endl;



// Funci�n que devuelve si una pocisi�n est� en el rango del tablero adecuado.
bool posValida(int i, int N){
    
    return (i < N);
}

// Funci�n que devuelve si con la cantidad de alfiles dada es imposible ubicarlos en el tablero.
bool juegoImposible(int K, int N){

    return( K > (2 * N) - 2);

}

// Idem juegoImposible pero para una divisi�n particular de alfiles.
bool divImposible(int K, int N){

    return( K > N - 1);

}

void mostrarMatriz2(const vvint &matriz){
	for (unsigned int i = 0; i < matriz.size(); i ++){
		for(unsigned int j = 0; j < matriz[i].size(); j++){
			cout << matriz[i][j] << ' ';
		}
		cout << endl;
	}
}

// Muestra la diags de diagonales (No es el tablero).
void mostrarMatriz(const vvbool &diags, int N){
    
    for (int i = 0; i < 4; i ++){
	for(int j = 0; j < N; j++){
	    cout << diags[i][j] << " ";
	}
	cout << endl;    
    }   
    
}

// Verifica si la diagonal derecha esta libre para una pocision dada.    
bool diagDerLibre(par pos, int N, vvbool &diags){
    
	
	if (pos.second >= pos.first){
	    return diags[0][pos.second - pos.first];
	}
	else{
	    return diags[1][pos.first - pos.second];
	}
    
} 

// Verifica si la diagonal izquierda esta libre para una pocision dada.
bool diagIzqLibre(par pos, int N, vvbool &diags){
   
    int suma = pos.first + pos.second;
    if (suma >= N)
	return  diags[2][suma - (N - 1)];
    else 
    	return diags[3][suma];
}

// Verifica si las diagonales que intersecan una posicion estan libres.
bool diagonalesLibres(par pos, int N, vvbool &diags){
    
    return diagDerLibre(pos, N, diags) && diagIzqLibre(pos, N, diags);
}        

// Setea la diagonal derecha de una posicion como ocupada o libre dependiendo del valor de seteo.
void setearDer(par pos, int N, vvbool &diags,bool seteo){
    
	if (pos.second >= pos.first){
	    diags[0][pos.second - pos.first] = seteo;
	}
	else{
	    diags[1][pos.first - pos.second] = seteo;
	}
    
} 

// Setea la diagonal izquierda de una posicion como ocupada o libre dependiendo del valor de seteo.
void setearIzq(par pos, int N, vvbool &diags,bool seteo){
   
    int suma = pos.first + pos.second;
    if (suma >= N)
	diags[2][suma - (N - 1)] = seteo;
    else 
    	diags[3][suma] = seteo;
}

// Setea las diagonales de una posicion como ocupada o libre dependiendo del valor de seteo.
void setearDiagonales(par pos, int N, vvbool &diags, bool seteo){
    
    setearDer(pos, N, diags, seteo);
    setearIzq(pos, N, diags, seteo);
}

// Pasa a la siguiente posici�n de un tablero, el mismo se recorre fila por fila.
par siguiente(par pos,int  N){
    par res;
    if (!posValida(((pos.second) + 2) , N)){
	    res.first = pos.first + 1;
	    if (N % 2 == 0){
		if (pos.second == N - 1)
		    res.second = 0;
		else
		    res.second = 1;
	    }
	    else{
		if (pos.second == N - 1)
		    res.second = 1;
		else
		    res.second = 0;
	   }     
    }
    else{
	res.first = pos.first;
	res.second = pos.second + 2;
    }
    return res;
}

vvint inicializarMemoria(){
		vvint memoria(9, vector<int>(0, -1));
		for (int i = 1; i < 9; i++){
			memoria[i] = vint(i*i+1,-1);
			memoria[i][0] = 1;
		}		
		return memoria;
}

// Funci�n que realiza el backtracking   
int littleBitshops(par pos, int N, int K,vvbool &diags, int puestos){
	
	int res = 0;
// 	mostrarMatriz(diags, N);
// 	cout << "i"<< pos.first << endl;
// 	cout << "j"<< pos.second << endl;
// 	cout << endl;
	if (K == 0){
	    return 1;
	}
	
	if (!posValida(pos.first, N))
	    return 0;

	
	if (diagonalesLibres(pos, N, diags)){
	    
	    setearDiagonales(pos, N, diags, 0);
	    if  ((puestos + 1) == K){
		res += 1;
		//mostrarMatriz(diags, N);
		//cout << res << endl ;
	    }
	    else
		res += littleBitshops(siguiente(pos, N), N, K, diags, puestos + 1);
	
	    setearDiagonales(pos, N, diags, 1); 
	}	
	
	    
	res += littleBitshops(siguiente(pos, N), N, K, diags, puestos);    
	    
	return res;
	
}

// Funci�n principal que se encarga de filtrar casos bordes y divide el tablero en negras y blancas.
int main(){
    vvint memoria = inicializarMemoria();
    int N, K =0;
    int res;
    int temp1;
    int temp2;
    par posN (0,0);
    par posB (0,1);

    cin >> N >> K;
    while (!(N <= 0 && K <= 0)){
		if (N > 8 || K > N*N) {
			cout << 0 << endl;
			cin >> N >> K; 
		} else {
			if (memoria[N][K] >= 0) {
				cout << memoria[N][K] << endl;
				cin >> N >> K; 
			} else {
				res = 0;
				temp1 = 0;
				temp2 = 0;
				if(N <= 8){
					if (N > 0){    
						if (N == 1){
							if (K <= 1) res = 1;
						} else{
							if(!juegoImposible(K,N)){
								if (N % 2 == 0){
									vuint resultados(K + 1, 0);
									for (int grupo = 0; grupo <= min(K, N - 1); grupo++ ){
										vvbool diags(4, vbool(N, 1));
										resultados[grupo] = littleBitshops(posN, N, grupo, diags, 0);
										
									}   
									for (int grupo = 0; grupo < (K/2); grupo++ ){
										res += 2 * ((resultados[grupo]) * (resultados[K - grupo]));
									}
									if (K % 2 == 0) {
										res += (resultados[K/2]) * (resultados[K/2]);
									} else {
										res += 2 * ((resultados[K/2]) * (resultados[K - (K/2)]));
									}
								} else {
									for (int grupo = 0; grupo <= K; grupo++ ){
										if(divImposible(grupo ,N) || divImposible(K - grupo,N)) {
											res += 0;
										} else{ 	    
											vvbool diags(4, vbool(N, 1));
											temp1 = littleBitshops(posN, N, grupo, diags, 0);
											temp2 = littleBitshops(posB, N, (K - grupo), diags, 0);
											res += temp1 * temp2;
										}
									}
								}
									
						   }	    
					   }
					}  
				}
				memoria[N][K] = res;
				cout << res << endl;
				cin >> N >> K; 
			}
		}

   }	
    //system("pause");
    return 0;
}
